home *** CD-ROM | disk | FTP | other *** search
- page 132,63,1,1
- opt rc
- title 'PAM Modulation/Demodulation'
-
- ;***************************************************************
- ;* PAM.ASM -- PAM Modulation/Demodulation and *
- ;* SSI drivers *
- ;* *
- ;* Provides interrupt based SSI handling, sample buffering *
- ;* and PAM modulation and demodulation. *
- ;* *
- ;* PAM modulation and demodulation is based on some ideas *
- ;* presented in book *
- ;* Lee, E., A., Messerschmitt, D., G.: *
- ;* "Digital Communication", *
- ;* Kluwer, 1988 *
- ;* *
- ;* Symbol syncronization is based on article *
- ;* Glisic, S., G.: *
- ;* "Symbol Syncronization in Digital Communications *
- ;* Using Partial Response CPM signaling", *
- ;* IEEE Trans. on Comm., Vol. 37, No. 3, March 1989 *
- ;* *
- ;* This module uses registers as follows: *
- ;* r0 - general purpose (temporary use) *
- ;* r2 - input sample write pointer *
- ;* r3 - output sample read pointer *
- ;* r4 - general purpose (temporary use) *
- ;* r6 - input sample read pointer *
- ;* r7 - output sample write pointer *
- ;* *
- ;* Copyright (C) 1991 by Alef Null. All rights reserved. *
- ;* Author(s): Jarkko Vuori, OH2LNS *
- ;* Modification(s): *
- ;***************************************************************
-
- nolist
- include 'ioequlc'
- list
-
- section PAM
- xdef ssi_ini,modem_i
- xdef m_loop
- xref putbit,getbit
- xref m_cra,m_crb,m_tde,m_sr,m_tx
-
- org p:
-
- nolist
- include 'macros'
- list
-
- ; PAM parameters
- poly equ $10800 ; G3RUH,K9NG scrambler polynomial (x^17 + x^12 + 1)
- rfilt equ 0.02 ; random walk filter constant
- adjlen equ 32 ; ADC timing control lenght (in samples)
-
- alpha equ 1.0/(2.0*13.0)*0.5
- level equ 0.05
- agcfilt equ 0.008
-
- ; module status bits
- toggle equ 6 ; every other bit counter
-
-
- ;****************************
- ;* SSI initialization *
- ;****************************
- ssi_ini
- ; initialize SSI,
- IF !DEBUG
- movep #$4000,x:m_cra ; 16 bit word
- movep #$f200,x:m_crb ; syncronous,word frame,ext clk
- ELSE
- movep #$4011,x:m_cra ; 16 bit word, abt. 19.2 ksamples/s
- movep #$f620,x:m_crb ; syncronous,word frame,ext clk
- ENDIF
-
- rts
-
-
- ;****************************
- ;* ADC & MODEM *
- ;* initialization *
- ;****************************
- modem_i
- ; program the A/D & D/A converter chip (TLC32044, master clock is 5.184MHz)
- ; disable A/D high-pass filter, disable loopback, disable AUX IN,
- ; select syncronous mode, select input span 3Vpp, insert sinx/x correction
- ; lowpass cutoff frequency at 6840Hz -> TA = 5 (SCF = 518.4kHz)
- ; sampling frequency is 19200Hz -> TB = 27
- ; unit sampling correction time 0.4uS -> TA' = 2
- pgmtlc %10101000,5,2,27
-
- ; sample handling,
- move #<insamp,r6
- move #<inN-N,n6
- move #<inN-1,m6
- move r6,r2
- move m6,m2
- movi 0,x:<samque
-
- move #<outsamp,r3
- move #<outN-1,m3
- move #<outsamp+1,r7
- move m3,m7
- movi <outfilt,x:<outfptr
-
- ; ADC command word and initial AGC
- movi 0,x:<adcnt
- movi 1.0/64.0,x:<agcgain
-
- rts
-
-
- ;****************************
- ;* Main Loop *
- ;****************************
- loop wait
- m_loop
-
-
- ;****************************
- ;* Receiver *
- ;****************************
- ; check if there are new samples received
- rec move r2,a
- move r6,x0
- cmp x0,a #<rcos,r0
- jeq <xmit
-
- ; yes, there indeed are new samples, check if receiver enabled
- jset #ptt,x:<status,xmit
-
- ; remove any DC-level (with high-pass filter)
- move x:(r6),a
- hpass a,20.0/19200.0,rdc
-
- ; AGC
- move a,x0
- move x:<agcgain,x1
- mpy x0,x1,a
- rep #6
- asl a
- move a,x:(r6)
-
- ; fractional spaced equalizer (FSE) - filter part
- conv 1,N,r6,r0,a
-
- ; limit to binary and queue received bits
- andi #$fe,ccr
- jmi <ssi_r00
- ori #$01,ccr
- ssi_r00 move x:<samque,b1
- rol b (r6)+n6
- move b1,x:<samque
-
- ; queue received samples
- move y:<dsample,b1
- move b1,y:<zsample
- move a,y:<dsample
-
- ; check if one symbol (2 samples) received
- bchg #toggle,x:<status
- jcc <ssi_end
-
- ; calculate the error
- neg a #-level,x1 ; x1 = alpha*(desired-filtered)
- jpl <in1
- move #level,x1
- in1 add x1,a #alpha,x0
- move a,x1
- mpyr x0,x1,b #<rcos,r0
-
- ; calculate a new agc
- move y:<dsample,a ; agcgain = (|desired|-|filtered|)*agcfilt+agcgain
- abs a #level,x0
- neg a #agcfilt,y1
- add x0,a b,x1
- move a,y0
- mpyr y0,y1,a x:<agcgain,x0
- add x0,a #<rcos,r4
- abs a
- move a,x:<agcgain
-
- jclr #dcd,x:<status,in2
- ; fractional Spaced Equalizer (FSE) - Adaptation part (LMS)
- move (r6)+ ; adjust to x(0)
- move x:(r6)+,x0 y:(r0)+,a ; get x(0), c0
- do #N,incupd
- macr x0,x1,a x:(r6)+,x0 y:(r0)+,y0 ; c = c + e(n) * x(n)
- tfr y0,a a,y:(r4)+ ; copy c, save new c
- incupd
- move (r6)- ; readjust sample pointer
- move (r6)-
- move (r6)+n6
- in2
-
- ; check if carrier present
- ; by checking when eye is open
- ; (enought difference between zero crossing sample and decision sample)
- move y:<dsample,a ; filter decision samples
- abs a
- lpass a,6.0/9600.0,rds
-
- move y:<zsample,b ; filter zero crossing samples
- abs b
- lpass b,6.0/9600.0,rzs
-
- sub b,a #level/7.0,x0 ; check their difference
- jclr #dcd,x:<status,lop
- move #level/1400.0,x0
- cmp x0,a
- jlt <doff
- jmp <ssi_r0a
- lop cmp x0,a
- jge <ssi_r0a
-
- ; DCD off detected
- doff bclr #dcd,x:<status
- jcc <ssi_r0b
- dcdoff
- move #>xcos,r0 ; reset input filter coeffs
- move #>rcos,r4
- do #N,_ecopy
- move y:(r0)+,a1
- move a1,y:(r4)+
- _ecopy
- jsset #req,x:<status,kickx ; call persistence routine if needed
- jmp <ssi_r0b
-
- ; DCD on detected
- ssi_r0a bset #dcd,x:<status
- jcs <ssi_r0b
- dcdon
-
- ; check if there are transitions (by analyzing the sample between decision samples)
- ; and set a register appropriately
- ssi_r0b clr a #rfilt,x1
- jclr #0,x:<samque,ssi_r2
- jset #2,x:<samque,ssi_r3
- ; 0x1
- move y:<zsample,a
- jmp <ssi_r3
- ssi_r2 jclr #2,x:<samque,ssi_r3
- ; 1x0
- move y:<zsample,a
- neg a
-
- ; filter (with integrator) those zero crossings
- ssi_r3 move a,x0
- mpyr x0,x1,a x:<rwalk,x0
- add x0,a #0.05,x0
- move a,x:<rwalk
-
- ; check if timing error too big (and advance/retard timing if necessary)
- cmpm x0,a #retard,b1
- jlo <ssi_r4
- tst a #advance,a1 ; threshold exceeded, adjust timing
- tmi b,a
- move a1,x:<adccmd
- move #adjlen,a1
- clr b a1,x:<adcnt
- move b1,x:<rwalk
-
- ; unscramble symbol, result in C
- ssi_r4 btst #0,x:<samque
- move x:<usrem,b1
- jcc <unscram
- move #>(poly<<1)|1,x0
- eor x0,b
- unscram lsr b
- move b1,x:<usrem
-
- ; make symbol decision (with NRZ-S decoding), databit in C, result in C
- rol b x:<prvrsym,x0
- eor x0,b b1,x:<prvrsym
- not b
- lsr b
-
- ; forward to the HDLC handler
- jsr <putbit
-
- ssi_end jmp <rec
-
-
- ;****************************
- ;* Transmitter *
- ;****************************
- ; check if we can calculate new samples
- xmit move r3,a
- move r7,x0
- cmp x0,a
- jeq <loop
-
- ; yes, check if the transmitter is on at all
- clr a
- jclr #ptt,x:<status,xmt2
-
- ; xmit mode, check if we need a new symbol
- bchg #toggle,x:<status
- jcc <xmt1
-
- ; yes, check on what phase we are
- jset #xmt,x:<status,xmt0
-
- ; training phase, send continuous preamble (zero pattern)
- andi #$fe,ccr
- jmp <morebit
-
- ; data phase, get a new bit to xmit
- xmt0 jsr <getbit
- jne <morebit
- ; there is no more bits to send, switch to receiving mode
- jsr <shutx
- andi #$fc,mr
-
- ; NRZ-S coding
- morebit rol a x:<prvxsym,x0
- not a
- eor x0,a #-1.0,x0
- ror a a1,x:<prvxsym
-
- ; scrambler, databit in C flag, result in a (-1 or 1)
- clr a
- rol a x:<srem,x0
- eor x0,a #-0.9,x1
- lsr a #>poly,x0
- jcc <scram
- eor x0,a
- scram move a1,x:<srem
- move #0.9,a
- tcc x1,a
-
- ; squared raised cosine shape output filter
- xmt1 move x:<outfptr,r4
- move #<xcos,r0
- move #<N-1,m4
- move a,x:(r4)
- conv 1,N,r4,r0,a
- move r4,x:<outfptr
- move #-1,m4
-
- ; send a new bit
- move a,x0 ; adjust output level
- move x:<gain,x1
- mpyr x0,x1,a #>$fffc<<8,x0
- xmt2 and x0,a x:<adcnt,b
- tst b #>1,y0 ; check if we must adjust timing
- jeq <xmt3
- sub y0,b x:<adccmd,x0 ; yes, add converter chip control cmds
- or x0,a b1,x:<adcnt
- xmt3 move a,x:(r7)+
-
- scx_end jmp <xmit
-
-
- ;****************************
- ;* DATA - AREA *
- ;****************************
-
- org x:
-
- adccmd ds 1 ; ADC timing command
- adcnt ds 1 ; ADC timing command counter
- samque ds 1 ; received sample queue
- prvrsym ds 1 ; previous received symbol
- prvxsym ds 1 ; previous xmitted symbol
- rwalk ds 1 ; random walk filter counter
- rds ds 2 ; desicion sample filter
- rzs ds 2 ; zero sample filter
- rdc ds 2 ; DC-level filter
- anacnt ds 1 ; signal quality analyzing lenght counter
- usrem ds 1
- srem ds 1
- outfptr ds 1 ; output filter pointer
- agcgain ds 1 ; current DAGC gain
-
- tmp ds 1
-
- org y:
-
- zsample ds 1 ; current zero crossing sample
- dsample ds 1 ; previous decision sample
-
- endsec
-
-
- ;****************************
- ;* M*BITS MODULO DATA *
- ;****************************
- section PAMData
- xdef N,inN,outN,rcos,xcos
- xdef insamp,outsamp,outfilt
-
- org x:
-
- ; PAM demod parameters
- N equ 13 ; samples per filter
- inN equ 16 ; input buffer lenght
- outN equ 8 ; output buffer lenght
-
- insamp ds inN
- outfilt ds N
- ds 16-N
- outsamp ds 8
-
- org y:
-
- ; receiver filter
- ; square root of raised cosine pulse filter constants
- ; beta = 6/16 = 0.375
- rcos dc -0.0082167989
- dc 0.0071048900
- dc 0.0254175599
- dc -0.0592829199
- dc -0.0434475299
- dc 0.2999202999
- dc 0.5512325000
- dc 0.2999202999
- dc -0.0434475299
- dc -0.0592829199
- dc 0.0254175599
- dc 0.0071048900
- dc -0.0082167989
-
- ; transmit filter
- ; square root of raised cosine pulse filter constants
- ; beta = 6/16 = 0.375
- xcos dc -0.0082167989
- dc 0.0071048900
- dc 0.0254175599
- dc -0.0592829199
- dc -0.0434475299
- dc 0.2999202999
- dc 0.5512325000
- dc 0.2999202999
- dc -0.0434475299
- dc -0.0592829199
- dc 0.0254175599
- dc 0.0071048900
- dc -0.0082167989
-
- endsec
-
- end
-